package main

import (
	"errors"
	"fmt"
)

// 可变参数
func intSum(i ...int) int {
	sum := 0
	for _, v := range i {
		sum = sum + v
	}
	return sum
}

// 混合参数
func hunhe(string2 string, int2 ...int) int {
	fmt.Println(string2)
	sum := 0
	for _, v := range int2 {
		sum = sum + v
	}
	return sum
}

// 命名返回值
func calc(x, y int) (sum, sub int) {
	sum = x + y
	sub = x - y
	return
}

func returnSlice(string2 string) []int {
	if string2 == "" {
		return nil //返回空切片直接返回nil就可以， nil也是一个空的切片
	}
	return nil
}

// 定义函数类型
type calculation func(int, int) int

func add(int2 int, int3 int) int {
	return int2 + int3
}
func sub(x, y int) int {
	return x - y
}

// 高阶函数
// 函数作为参数
func calc1(x, y int, op func(int, int) int) int {
	return op(x, y)
}

// 函数作为返回值
func do(s string) (func(int, int) int, error) {
	switch s {
	case "+":
		return add, nil
	case "-":
		return sub, nil
	default:
		err := errors.New("无法识别的操作符")
		return nil, err
	}
}

// 匿名函数
func niming() {
	add := func(x, y int) {
		fmt.Println(x + y)
	}
	add(10, 20)

	func(x, y int) {
		fmt.Println(x + y)
	}(1, 3)
}

/*
*
闭包函数
闭包指的是一个函数和与其相关的引用环境组合而成的实体
*/
func adder() func(int) int {
	var x int
	return func(y int) int {
		x += y
		return x
	}
}

func adder2(x int) func(int) int {

	return func(y int) int {
		x += y
		return x
	}
}

func calc3(base int) (func(int) int, func(int) int) {
	add := func(int2 int) int {
		base += int2
		return base
	}
	sub := func(int2 int) int {
		base -= int2
		return base
	}
	return add, sub
}

func bi() func(int2 int) int {
	x := 1
	return func(y int) int {
		return x + y
	}
}

func main() {

	f := bi()
	for i := 1; i < 5; i++ {
		fmt.Println(f(i))
	}
	return
	//sum := intSum(1,2,3,4,5)
	a := []int{1, 2, 3, 4}
	sum := intSum(a...)
	fmt.Println(sum)
	return
	//sum = hunhe("haha",1,2,3,4,5)
	//fmt.Println(sum)
	//s, su := calc(10,2)
	//fmt.Println(s, su)
	//
	//var c calculation
	//c = add
	//c1 := c(1,3)
	//fmt.Println(c1)
	//
	//res := calc1(10, 20, add)
	//fmt.Println(res)
	//f := adder()
	//f1 := adder2(5)
	//fmt.Println(f(10)) //10
	//fmt.Println(f(20)) //30
	//fmt.Println(f(30)) //60
	//fmt.Println(f1(10)) //10
	//fmt.Println(f1(20)) //30
	//f3, f4 := calc3(100)
	//fmt.Println(f3(10))
	//fmt.Println(f4(40))
	//
	fmt.Println(df1()) //5
	fmt.Println(df2()) //6
	fmt.Println(df3()) //5
	fmt.Println(df4()) //5
	//
	//fmt.Println()
	//x := 1
	//y := 2
	//defer deferMianShi("AA", x, deferMianShi("A", x, y))
	//x = 10
	//defer deferMianShi("BB", x, deferMianShi("B", x, y))
	//y = 20

	//分金币
	//dispatchCoin()
	//fmt.Println(coins)
	//fmt.Println(distribution)
}

var (
	coins = 50
	users = []string{
		"Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
	}
	distribution = make(map[string]int, len(users))
)

func dispatchCoin() {
	for _, user := range users {
		for _, name := range user {
			switch name {
			case 'e', 'E':
				distribution[user] = distribution[user] + 1
				coins = coins - 1
			case 'i', 'I':
				distribution[user] = distribution[user] + 2
				coins = coins - 2
			case 'o', 'O':
				distribution[user] = distribution[user] + 3
				coins = coins - 3
			case 'u', 'U':
				distribution[user] = distribution[user] + 4
				coins = coins - 4
			}
		}
	}
}

func deferMianShi(index string, a, b int) int {
	ret := a + b
	fmt.Println(index, a, b, ret)
	return ret
}

func df1() int {
	x := 5
	defer func() {
		x++
	}()
	return x
}
func df2() (x int) {
	defer func() {
		x++
	}()
	return 5
}
func df3() (y int) {
	x := 5
	defer func() {
		x++
	}()
	return x
}

func df4() (x int) {
	defer func(x int) {
		x++
	}(x)
	return 5
}
